package com.zf.bm.common.core.sys.web;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.zf.bm.common.core.log.annotation.SysLog;
import com.zf.bm.common.core.sys.entity.Menu;
import com.zf.bm.common.core.sys.entity.Role;
import com.zf.bm.common.core.sys.entity.User;
import com.zf.bm.common.core.sys.service.MenuService;
import com.zf.bm.common.core.sys.service.RoleService;
import com.zf.bm.common.core.sys.service.SystemService;
import com.zf.bm.common.dto.ObjectConvert;
import com.zf.bm.common.core.sys.dto.MenuDTO;
import com.zf.bm.common.core.sys.dto.MenuTreeDTO;
import com.zf.bm.common.web.BaseController;
import com.zf.bm.modules.policy.util.ExcludeEmptyQueryWrapper;
import com.zf.bm.vo.MenuInfoVo;
import com.zf.bm.vo.MenuVo;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 菜单Controller
 */
@RestController
@RequestMapping(value = "${adminPath}/menus", method = {RequestMethod.GET, RequestMethod.POST})
public class MenuController extends BaseController {

    @Autowired
    private SystemService systemService;

    @Autowired
    private MenuService menuService;

    @Autowired
    private RoleService roleService;

    @SysLog("菜单操作")
    @RequiresPermissions("sys:menu:edit")
    @PostMapping(value = "save")
    public Result save(@RequestBody MenuInfoVo vo) {
        if (!UserUtils.getUser().isAdmin()) {
            return new Result(ResultStatus.FAIL.getCode(), "越权操作，只有超级管理员才能添加或修改数据！");
        }
        ObjectConvert<Menu> convert = new ObjectConvert();
        Menu menu = convert.toObj(vo, new Menu());
        Menu parentManu = vo.getParent();
        menu.setParentIds(parentManu.getParentIds() + vo.getPid() + ",");
        menu.setParent(parentManu);
        menu.setIsShow(StringUtil.isNotBlank(vo.getPermissions()) ? "0" : "1");
        systemService.saveMenu(menu);
        return new Result("保存菜单'" + menu.getName() + "'成功");
    }

    @RequestMapping("/{show}/build")
    public Result menuByUser(@PathVariable("show") String show) {
        List<MenuVo> menuDTOTree = getMenus(show);
        if (!Collections3.isEmpty(menuDTOTree)) {
            Map<String, Object> resultMenu = Maps.newHashMap();
            resultMenu.put("content", menuDTOTree.get(0).getChildren());
            Result result = new Result(resultMenu);
            return result;
        } else {
            logger.info("菜单为空");
            return new Result(ResultStatus.DATA_NOT_POWER);
        }
    }


    @RequestMapping("/menuList")
    @RequiresPermissions("sys:menu:edit")
    public Result menuList() {
        List<MenuVo> menuDTOTree = getMenus(null).get(0).getChildren();
        return new Result(menuDTOTree);
    }


    @RequestMapping("/{show}/menuTree")
    public Result menuTree(@PathVariable("show") String show) {
        List<Menu> menuList = filterMenu(show);
        List<MenuTreeDTO> menuDTOS = Lists.newArrayList();
        for (Menu m : menuList) {
            MenuTreeDTO dto = new MenuTreeDTO();
            dto.setLabel(m.getName());
            dto.setId(m.getId());
            dto.setPId(m.getParentId());
            menuDTOS.add(dto);
        }
        List<MenuTreeDTO> trees = new ArrayList<>();
        addChild(menuDTOS, trees);

        Map<String, List<MenuTreeDTO>> result = Maps.newHashMap();
        result.put("data", trees);
        return new Result(result);
    }


    @RequestMapping("/{show}/menuTreeAll")
    public Result menuTreeAll(@PathVariable("show") String show,@RequestBody User sysUser) {
        List<Menu> menuList = filterMenuAll(show);

        menuList = filterName(sysUser, menuList);

        List<MenuTreeDTO> menuDTOS = Lists.newArrayList();
        for (Menu m : menuList) {
            MenuTreeDTO dto = new MenuTreeDTO();
            dto.setLabel(m.getName());
            dto.setId(m.getId());
            dto.setPId(m.getParentId());
            menuDTOS.add(dto);
        }
        List<MenuTreeDTO> trees = new ArrayList<MenuTreeDTO>();
        addChild(menuDTOS, trees);

        Map<String, List<MenuTreeDTO>> result = Maps.newHashMap();
        result.put("data", trees);
        return new Result(result);
    }

    private static void addChild(List<MenuTreeDTO> menuDTOS, List<MenuTreeDTO> trees) {
        for (MenuTreeDTO menuDTO : menuDTOS) {
            if ("0".equals(menuDTO.getPId().toString())) {
                trees.add(menuDTO);
            }
            for (MenuTreeDTO it : menuDTOS) {
                if (it.getPId().equals(menuDTO.getId())) {
                    if (menuDTO.getChildren() == null) {
                        menuDTO.setChildren(new ArrayList<MenuTreeDTO>());
                    }
                    menuDTO.getChildren().add(it);
                }
            }
        }
    }

    private List<Menu> filterName(User sysUser, List<Menu> menuList) {
        if (ValidatorUtil.isEmptyObj(sysUser.getId())) {
            return menuList;
        }

        Role id = roleService.getOne(new ExcludeEmptyQueryWrapper<Role>().eq("id", sysUser.getId()));
        if (ValidatorUtil.isNotEmptyObj(id) && "admin".equals(id.getRemarks())) {
            menuList = menuList.stream().filter(i -> !"字典管理".equals(i.getName())).collect(Collectors.toList());
        }
        return menuList;
    }


    @SysLog("菜单删除")
    @RequiresPermissions("sys:menu:edit")
    @RequestMapping(value = "delete")
    public Result delete(@RequestBody MenuInfoVo vo) {
        systemService.deleteMenu(new Menu(vo.getId()).selectById());
        return new Result("删除菜单成功！");
    }



    /**
     * 多项目统一管理添加方法
     *
     * @param show
     * @param menuList
     * @return
     */
    private Stream<Menu> filterMenu(String show, List<Menu> menuList) {

        //过虑隐藏菜单isShow=0
        Stream<Menu> stream = menuList.stream();
        if (StringUtil.isNotEmpty(show) && !"2".equals(show)) {
            stream = stream.filter(m -> show.equals(m.getIsShow()));
        }
        stream = stream.filter(i -> "1".equals(i.getIsShow()));
        return stream;
    }

    private Stream<Menu> filterSysMenu(String show, List<Menu> menuList) {

        //过虑隐藏菜单isShow=0
        Stream<Menu> stream = menuList.stream();
        if (StringUtil.isNotEmpty(show) && !"2".equals(show)) {
            stream = stream.filter(m -> show.equals(m.getIsShow()));
        }
        stream = stream.filter(i -> "1".equals(i.getIsShow())).filter(i -> "0".equals(i.getIsSys())).filter(i -> !"/broad/menu".equals(i.getComponent()));
        return stream;
    }


    /**
     * 菜单
     *
     * @return
     */
    private List<Menu> filterMenuAll(String show) {
        List<Menu> menuList = menuService.list(Wrappers.query(new Menu()));
        if (!Collections3.isEmpty(menuList)) {
            Stream<Menu> stream = filterSysMenu(show, menuList);
            return stream.collect(Collectors.toList());

        }
        return menuList;
    }

    private List<Menu> filterMenu(String show) {
        List<Menu> menuList = UserUtils.getMenuList();
        if (!Collections3.isEmpty(menuList)) {
            Stream<Menu> stream = filterMenu(show, menuList);
            return stream.collect(Collectors.toList());

        }
        return menuList;
    }


    /**
     * 菜单
     *
     * @param show 2是加载全部包括隐藏菜单
     * @return
     */
    private List<MenuDTO> getMenuDTO(String show) {
        List<Menu> menuList = UserUtils.getMenuList();
        List<MenuDTO> menuDTOS = Lists.newArrayList();
        if (!Collections3.isEmpty(menuList)) {
            Stream<Menu> stream = filterMenu(show, menuList);
            stream.forEach(m -> {
                MenuDTO menuDTO = new MenuDTO();
                ObjectConvert<MenuDTO> objectToDto = new ObjectConvert();
                menuDTO = objectToDto.toDto(m, menuDTO);
                menuDTOS.add(menuDTO);
            });
        }
        return menuDTOS;
    }


    /**
     * 菜单
     *
     * @return
     */
    private List<MenuVo> getMenus(String show) {
        List<MenuDTO> menuDTO = (List<MenuDTO>) buildTree(getMenuDTO(show)).get("content");
        List<MenuVo> menuDTOTree = buildMenus(menuDTO);
        return menuDTOTree;
    }
}
